package com.rykj.qxj.test.xtest.httpclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;

public class HttpClientUtils {
	private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
	private static final String charSet = "UTF-8";
	
    private static HttpConnectionManager connectionManager;
    
    public static void getConnection() {
    	
    	if (connectionManager == null) {
    		// 创建一个线程安全的HTTP连接池
            connectionManager = new MultiThreadedHttpConnectionManager();
            HttpConnectionManagerParams params = new HttpConnectionManagerParams();
            // 连接建立超时
            params.setConnectionTimeout(60000);
            // 数据等待超时
            params.setSoTimeout(30000);
            // 默认每个Host最多10个连接S
            params.setDefaultMaxConnectionsPerHost(50);
            // 最大连接数（所有Host加起来）
            params.setMaxTotalConnections(500);
            connectionManager.setParams(params);
		}
       
    }

    /**
     * 调用外部系统
     * @param json
     * @param uri
     * @return
     */
    public String sendMsHttpPost(Map<String, String> paramMap ,String uri,String defCharset){
    	getConnection();
        // 发送报文
        org.apache.commons.httpclient.HttpClient httpClient = new org.apache.commons.httpclient.HttpClient(connectionManager);
        PostMethod postMethod = new PostMethod(uri);
        String resJson = "";
        postMethod.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset="+defCharset);
        try {
			if (null != paramMap) {
	            Set<String> keys = paramMap.keySet();
	            for (String key : keys) {
	                if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(paramMap.get(key))) {
	                    String value = paramMap.get(key);
	                    postMethod.setParameter(key, value);
	                }
	            }
	        }
			
            httpClient.executeMethod(postMethod);
            resJson = stream2String(postMethod.getResponseBodyAsStream());
            logger.debug("响应报文[{}]",resJson);
        } catch (UnsupportedEncodingException e) {
        	logger.error("交易报文编码异常[{}]",e.getMessage());
        	e.printStackTrace();
        } catch (HttpException e) {
        	logger.error("交易http连接异常[{}]",e.getMessage());
        	e.printStackTrace();
		} catch (IOException e) {
			logger.error("交易http读取异常[{}]",e.getMessage());
			e.printStackTrace();
		} finally {
            postMethod.releaseConnection();
        }
       
		return resJson;
    }

	/**
	 * json转Map
	 * @param jsonStr
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> json2Map(String jsonStr) {
		if(logger.isDebugEnabled())
			logger.debug("json转Map:[{}]",jsonStr);
		
		ObjectMapper mapper = new ObjectMapper();
		Map<String, String> map = new HashMap<String, String>();
		try {
			map = mapper.readValue(jsonStr, Map.class);
		} catch (Exception e) {
			if(logger.isErrorEnabled())
				logger.error(e.getMessage(),e);
			e.printStackTrace();
		}
		return map;
	}
	
	public Map<String, Object> json2Map2(String jsonStr) {
		if(logger.isDebugEnabled())
			logger.debug("json转Map:[{}]",jsonStr);
		
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			map = mapper.readValue(jsonStr, Map.class);
		} catch (Exception e) {
			if(logger.isErrorEnabled())
				logger.error(e.getMessage(),e);
			e.printStackTrace();
		}
		return map;
	}
	public String send(String uri, String jsonReq) {
		getConnection();
        // 发送报文
        org.apache.commons.httpclient.HttpClient httpClient = new org.apache.commons.httpclient.HttpClient(connectionManager);
        PostMethod method = new PostMethod(uri);
        method.addRequestHeader("Content-Type", "application/json");
        try {
        	logger.debug("发送报文{}",jsonReq);
        	method.setRequestEntity(new StringRequestEntity(jsonReq,null, charSet));
            httpClient.executeMethod(method);
            String jsonRes = stream2String(method.getResponseBodyAsStream());
            logger.debug("响应报文{}",jsonRes);
            return jsonRes;
        } catch (UnsupportedEncodingException e) {
        	logger.error("交易报文编码异常[{}]",e.getMessage());
        	e.printStackTrace();
        } catch (HttpException e) {
        	logger.error("交易http连接异常[{}]",e.getMessage());
        	e.printStackTrace();
		} catch (IOException e) {
			logger.error("交易http读取异常[{}]",e.getMessage());
			e.printStackTrace();
		} catch (Exception e) {
        	logger.error("发送异常[{}]",e.getMessage());
        	e.printStackTrace();
        } finally {
            method.releaseConnection();
        }
        return null;
    }
	
	public <T> String send(String uri, T t ) {
		ObjectMapper objectMapper = new ObjectMapper();
		getConnection();
        // 发送报文
        org.apache.commons.httpclient.HttpClient httpClient = new org.apache.commons.httpclient.HttpClient(connectionManager);
        PostMethod method = new PostMethod(uri);
        method.addRequestHeader("Content-Type", "application/json");
        try {
        	String  params = objectMapper.writeValueAsString(t);
        	logger.debug("发送报文{}",params);
        	method.setRequestEntity(new StringRequestEntity(params,null, charSet));
            httpClient.executeMethod(method);
            String jsonRes = stream2String(method.getResponseBodyAsStream());
            logger.debug("响应报文{}",jsonRes);
            return jsonRes;
        } catch (UnsupportedEncodingException e) {
        	logger.error("交易报文编码异常[{}]",e.getMessage());
        } catch (HttpException e) {
        	logger.error("交易http连接异常[{}]",e.getMessage());
		} catch (IOException e) {
			logger.error("交易http读取异常[{}]",e.getMessage());
		} catch (Exception e) {
        	logger.error("发送异常[{}]",e.getMessage());
        } finally {
            method.releaseConnection();
        }
        return null;
    }
	// 解压缩
    public static String uncompress(InputStream gzippedResponse) throws IOException {

        InputStream decompressedResponse = new GZIPInputStream(gzippedResponse);
        Reader reader = new InputStreamReader(decompressedResponse, "UTF-8");
        StringWriter writer = new StringWriter();

        char[] buffer = new char[10240];
        for(int length = 0; (length = reader.read(buffer)) > 0;){
            writer.write(buffer, 0, length);
        }

        writer.close();
        reader.close();
        decompressedResponse.close();
        gzippedResponse.close();

        return writer.toString();
    }
    //无需解压
    public static String compress(InputStream responseStr) throws IOException {

        Reader reader = new InputStreamReader(responseStr, "UTF-8");
        StringWriter writer = new StringWriter();

        char[] buffer = new char[10240];
        for(int length = 0; (length = reader.read(buffer)) > 0;){
            writer.write(buffer, 0, length);
        }

        writer.close();
        reader.close();
        responseStr.close();

        return writer.toString();
    }
	public static String sendGet(String urls,String token) throws IOException{
		String resJson = "";
        URL url = new URL(urls);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch");
        connection.setRequestProperty("Accept", "application/json");
        connection.setRequestProperty("Authorization", "token "+token+"");
        connection.connect();
        /*System.out.println(uncompress(connection.getInputStream()));*/
        /*System.out.println(compress(connection.getInputStream()));*/
        try {
        	resJson = compress(connection.getInputStream());
        	connection.disconnect();
		} catch (ArithmeticException  e) {
			System.out.println(e);
		}
		 logger.debug("响应报文[{}]",resJson);
		return resJson;
	}
	 /**
     * 调用外部系统
     * @param json
     * @param uri
     * @return
     */
    public static String sendMsHttpGet(Map<String, String> paramMap ,String uri,String defCharset,String appKey){
    	getConnection();
        // 发送报文
        org.apache.commons.httpclient.HttpClient httpClient = new org.apache.commons.httpclient.HttpClient(connectionManager);
        GetMethod getMethod = new GetMethod(uri);
        getMethod.setRequestHeader("appKey", appKey);   //添加的一个参数
        String resJson = "";
        org.apache.commons.httpclient.params.HttpMethodParams httpMethodParams = new  org.apache.commons.httpclient.params.HttpMethodParams();
        httpMethodParams.setContentCharset(defCharset);
        getMethod.setParams(httpMethodParams);
        try {
			if (null != paramMap) {
	            Set<String> keys = paramMap.keySet();
	            NameValuePair nameValuePair[] = new NameValuePair[paramMap.entrySet().size()];
	            int i=0;
	            for (String key : keys) {
	                if (StringUtils.isNotBlank(key)) {
	                    String value = paramMap.get(key);
	                    nameValuePair[i]=new NameValuePair(key,value);
	                    i++;
	                }
	            }
                String queryString = EncodingUtil.formUrlEncode(nameValuePair, defCharset);
				getMethod.setQueryString(queryString);

	        }
			
            httpClient.executeMethod(getMethod);
            
            resJson = stream2String(getMethod.getResponseBodyAsStream());
            logger.debug("响应报文[{}]",resJson);
        } catch (UnsupportedEncodingException e) {
        	logger.error("交易报文编码异常[{}]",e.getMessage());
        	e.printStackTrace();
        } catch (HttpException e) {
        	logger.error("交易http连接异常[{}]",e.getMessage());
        	e.printStackTrace();
		} catch (IOException e) {
			logger.error("交易http读取异常[{}]",e.getMessage());
			e.printStackTrace();
		} finally {
            getMethod.releaseConnection();
        }
		return resJson;
    }
    
    private static String stream2String(InputStream inputStream) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
        StringBuffer strBuff = new StringBuffer();
        String str = "";
        while((str = reader.readLine())!=null){
        	strBuff.append(str);
        }
    	return strBuff.toString();
    }
    
    
	public <T> String getHttpClientUtil(String url , T t ) {
		ObjectMapper objectMapper = new ObjectMapper();
		// 发送报文
    	HttpClient httpClient = new HttpClient();
    	httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
    	httpClient.getHttpConnectionManager().getParams().setSoTimeout(10000);
    	PostMethod postMethod = new PostMethod(url);
		String resultJsonString = "";
	    try {
	    	String  params = objectMapper.writeValueAsString(t);
	    	
	    	postMethod.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset="+"UTF-8");
	    	logger.info("推送报文参数，params====" + params);
	    	RequestEntity requestEntity = new StringRequestEntity(params,"text/xml","UTF-8");
	    	postMethod.setRequestEntity(requestEntity);
	        httpClient.executeMethod(postMethod);
	        resultJsonString = postMethod.getResponseBodyAsString();
	        logger.info("推送返回报文:" + resultJsonString);
	    } catch (HttpException e) {
	    	logger.error("客户端异常:" + e.getMessage());
	    } catch (IOException e) {
	    	logger.error("客户端异常:" + e.getMessage());
	    } finally {
	        postMethod.releaseConnection();
	    }
		return resultJsonString;
	}
	@SuppressWarnings("resource")
	public static <T> String doHttpsPost(String url, T t) {
		SSLClient httpClient = null;
		HttpPost httpPost = null;
		String result = null;
		try {
			httpClient = new SSLClient();
			httpPost = new HttpPost(url);
			httpPost.addHeader("Content-Type", "application/json");
			String jsonstr = JSON.toJSONString(t);
			StringEntity se = new StringEntity(jsonstr);
			se.setContentType("text/json");
			se.setContentEncoding(new BasicHeader("Content-Type",
					"application/json"));
			httpPost.setEntity(se);
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				logger.info("HttpResponse=" + response.getEntity());
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					result = EntityUtils.toString(resEntity, "UTF-8");
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return result;
	}
	public static String sendMsHttpPost2(Object req ,String uri,String defCharset,String appKey){
        // 发送报文
    	HttpClient httpClient = new HttpClient();
    	httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
    	httpClient.getHttpConnectionManager().getParams().setSoTimeout(30000);        
    	PostMethod postMethod = new PostMethod(uri);
    	postMethod.setRequestHeader("appKey", appKey);
        String resJson = "";
        postMethod.addRequestHeader("Content-Type", "application/json");
        try {
        	String json = JSON.toJSONString(req);
            postMethod.setRequestEntity(new StringRequestEntity(json ,null, "UTF-8"));
            httpClient.executeMethod(postMethod);
            resJson = postMethod.getResponseBodyAsString();
            logger.debug("响应报文[{}]",resJson);
        } catch (UnsupportedEncodingException e) {
        	logger.error("交易报文编码异常[{}]",e.getMessage());
        	e.printStackTrace();
        } catch (HttpException e) {
        	logger.error("交易http连接异常[{}]",e.getMessage());
        	e.printStackTrace();
		} catch (IOException e) {
			logger.error("交易http读取异常[{}]",e.getMessage());
			e.printStackTrace();
		} finally {
            postMethod.releaseConnection();
        }
       
		return resJson;
    }
}
